package com.uplift.sec.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.uplift.common.Const;
import com.uplift.common.result.ResultWrapper;
import com.uplift.common.utils.URLMatcher;
import com.uplift.common.utils.WebMessage;
import com.uplift.sec.SecurityContext;

/**
 * 安全认证过滤器
 * 
 * @author bcwang
 *
 */
public class SecurityFilter extends OncePerRequestFilter {

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		// 检查是否为不受保护的地址
		boolean unprotect = false;
		String url = request.getServletPath();
		for (String unprotectUrl : Const.UNPROTECT_URL) {
			unprotect = URLMatcher.match(unprotectUrl, url);
			if (unprotect) {
				break;
			}
		}
		// 1、不受保护的地址直接放行
		// 2、受保护的地址验证是否登录，如果登录设置SecurityContext，否则JSON响应
		if (unprotect) {
			filterChain.doFilter(request, response);
		} else {
			String authorization = request.getHeader("Authorization");
			// 如果认证头信息不为空，则首选按认证头信息处理
			// 其次处理web登录
			if (StringUtils.isBlank(authorization)) {
				WebMessage.sendJsonMessageIgnoreEx(response, ResultWrapper.wrapMap(null, ResultWrapper.FAIL, "无权访问"));
			} else {
				try {
					String token = StringUtils.substringAfter(authorization, " ");
					Algorithm algorithm = Algorithm.HMAC256(Const.JWT_SECRET);
					JWTVerifier jwtVerifier = JWT.require(algorithm).build();
					DecodedJWT decodedJWT = jwtVerifier.verify(token);

					Claim claim = decodedJWT.getClaim("userId");

					String userId = claim.asString();

					SecurityContext.setUserId(userId);
					
					filterChain.doFilter(request, response);
				} catch (JWTVerificationException e) {
					e.printStackTrace();
					if (e instanceof TokenExpiredException) {
						WebMessage.sendJsonMessageIgnoreEx(response, ResultWrapper.wrapMap(null, ResultWrapper.FAIL, "无权访问，token已经失效"));
					} else {
						WebMessage.sendJsonMessageIgnoreEx(response, ResultWrapper.wrapMap(null, ResultWrapper.FAIL, "无权访问，token验证失败"));
					}
				}
			}
		}
	}

	
	
}
